home *** CD-ROM | disk | FTP | other *** search
- //=====================================================================
- //
- // loadprog.cpp
- //
- // Actually load new executable images, and Borland debug symbol
- // information if it exists.
- //
- // Copyright (c) 1994, Kevin Morgan, All rights reserved.
- //
- //=====================================================================
- //
- //#define DEBUG
- #ifdef DEBUG
- //#define DEBUGNAMES
- //#define DEBUGSYMBOLS
- #endif
-
- #define errprint printf
-
- #include "dpmirun.h"
-
- #include "exedef.h" // defines structure of New Executable .EXE image
-
- class near DebugInfo;
-
- //=====================================================================
- //
- // RealModuleLoader
- // this class implements the loading process that is abstracted
- // in ModuleLoader.
- //
- //=====================================================================
- class near RealModuleLoader : public ModuleLoader
- {
- friend DebugInfo;
- protected:
- SegmentTable *segTable;
-
- Selector *selectors;
-
- int loadErrorCount;
-
- DWORD headeroffset, lastbyte;
-
- long endOfImage; // positions after relocations for last segment
-
- HEADER header;
-
- NEHEADER newHeader;
-
- DebugInfo *debugInfo;
-
- char fname[80];
-
- int inf;
-
-
- public:
- RealModuleLoader() :
- segTable(0),
- selectors(0),
- loadErrorCount(0),
- debugInfo(0),
- endOfImage(0),
- ModuleLoader() { }
- virtual void _far *entryPoint();
- virtual char *describeFaultPc(WORD& nearCs, WORD cs, WORD ip);
- virtual void far *getStack(unsigned);
- virtual void loadExecutable(char *);
- virtual void adjustSelectors();
- virtual int loadErrors() { return loadErrorCount; }
-
- // implementation specific methods
- Selector *allocSelectors(int);
- SegmentTable *allocSegTables(int);
- int getLogicalSelector(WORD cs, WORD& lcs);
- void read_segment_table(int inf, int nsegs, SegmentTable *tablePtr);
- int readSegmentData(int nsegs, SegmentTable *tablePtr, Selector *selectors);
- int readRelocations(int segNr, SegmentTable *st, Selector *selectors);
- };
-
- FILE *loadlogf = 0;
-
-
- //=====================================================================
- //
- // dprintf -- print diagnostic info to our diag file.
- //
- //=====================================================================
- #pragma argsused
- void dprintf(char *fmt,...)
- {
- #ifdef DEBUG
- va_list argptr;
- char vbuf[160];
- va_start(argptr, fmt);
- vsprintf(vbuf, fmt, argptr);
- va_end(argptr);
- if (!loadlogf) {
- loadlogf = fopen("diag.tmp","w+t");
- }
- if (loadlogf) {
- fprintf(loadlogf, "%s", vbuf);
- fflush(loadlogf);
- }
- #endif
- }
-
- //=====================================================================
- //
- // kprintf -- print diagnostic info to our diag file.
- //
- //=====================================================================
- #pragma argsused
- void kprintf(char *fmt,...)
- {
- va_list argptr;
- char vbuf[160];
- va_start(argptr, fmt);
- vsprintf(vbuf, fmt, argptr);
- va_end(argptr);
- if (!loadlogf) {
- loadlogf = fopen("diag.tmp","w+t");
- }
- if (loadlogf) {
- fprintf(loadlogf, "%s", vbuf);
- fflush(loadlogf);
- }
- printf("%s", vbuf);
- fflush(stdout);
- }
-
- //=====================================================================
- //
- // lread -- read from a file into a far memory region
- //
- //=====================================================================
- DWORD lread(int inf, char _far *p, DWORD len)
- {
- DWORD tbytes = 0;
- DWORD bytes;
- char *buf = new char[4096];
- while (len>0) {
- DWORD sz = len;
- if (len>4096) sz = 4096;
- bytes = read(inf, buf, sz);
- if (bytes==0xffff) { tbytes=bytes; break; }
- _fmemcpy(p, buf, sz);
- p += sz;
- tbytes+=bytes;
- len -= bytes;
- }
- delete [] buf;
- return tbytes;
- }
-
- #ifdef DIAGS
- //=====================================================================
- //
- // dump_dpmi_information
- //
- // interrogate our dpmi server and print what we find.
- //
- //=====================================================================
- int dump_dpmi_information(int , char *[])
- {
- clrscr();
- gotoxy(1,1);
- {
- dprintf("get dpmi version\n");
- int maj,min,flags;
- int res = Dpmi.getVersion(maj,min,flags);
- if (res!=DPMI_OK)
- dprintf("no DPMI 0.9 capabilities\n");
- else {
- dprintf("DPMI ver %d.%d\n", maj,min);
- dprintf("running on 32-bit DPMI: %s\n", flags&1?"yes":"no");
- dprintf("interrupts in RM : %s\n", flags&2?"yes":"no");
- dprintf("virtual memory support: %s\n", flags&4?"yes":"no");
- }
- }
-
-
- {
- static char buf[128];
- char _far *bufp = buf;
- int flags;
- int res = Dpmi.getCapabilities(bufp, flags);
- if (res!=DPMI_OK)
- dprintf("no DPMI 1.0 capabilities\n");
- else {
- dprintf("DPMI ver %d.%d %s\n", buf[0], buf[1], buf+2);
- dprintf("page accessed : %s\n", flags&1?"yes":"no");
- dprintf("exceptions restartable: %s\n", flags&2?"yes":"no");
- dprintf("device mapping support: %s\n", flags&4?"yes":"no");
- dprintf("conventional mapping : %s\n", flags&8?"yes":"no");
- dprintf("demand zero-fill : %s\n", flags&16?"yes":"no");
- dprintf("write protect client : %s\n", flags&32?"yes":"no");
- dprintf("write protect host : %s\n", flags&64?"yes":"no");
- }
- }
-
- return 0;
- }
- #endif
-
- //=====================================================================
- //
- // dumpItem
- //
- // diagnostic hex dump of areas read
- //
- //=====================================================================
- void dumpItem(char *title, void *ptr, size_t sz)
- {
- unsigned *p = (unsigned *)ptr;
- dprintf("%s\n", title);
- int i;
- for (i=0;i<sz/2;i++) {
- if (i%8==0) dprintf("%04x: ",i);
- dprintf("%04x ", *p++);
- if (i%8==7) dprintf("\n");
- }
- dprintf("\n");
- }
-
- //=====================================================================
- //
- // FarMemoryPool
- //
- // Manage a memory pool allocated with DPMI
- //
- //=====================================================================
- class FarMemoryPool
- {
- protected:
- Selector poolSeg;
- unsigned long poolSize;
- unsigned long poolCnt;
- unsigned long allocationUnit;
- public:
- FarMemoryPool(unsigned long allocSz=32768) :
- poolSeg(0), poolSize(0),
- poolCnt(0), allocationUnit(allocSz) { }
- void far *getMemory(unsigned long sz);
- };
-
-
- void far *FarMemoryPool::getMemory(unsigned long sz)
- {
- // DWORD alignment
- sz += 3;
- sz -= (sz&3);
-
- if (poolSeg==0 || poolCnt+sz>poolSize) { // need to allocate
- poolSeg = 0;
- poolCnt = 0;
- if (Dpmi.getMappedMemory(allocationUnit, poolSeg, AccessRightsData)!=DPMI_OK)
- return 0;
- poolSize = allocationUnit;
- }
- if (poolSeg==0 || poolCnt+sz>poolSize) // Oops!
- return 0;
- void far *p = MK_FP(poolSeg, poolCnt);
- poolCnt += sz;
- return p;
- }
-
- FarMemoryPool pool;
-
- //=====================================================================
- //
- // SparseObjectTable
- //
- // A table of objects stored in protected mode memory
- //
- // We allow a number of objects limited only by available memory,
- // despite the protected mode 64K segment limit.
- //
- //=====================================================================
- typedef void SparseObject;
-
- typedef SparseObject far *SparseObjectPtr;
-
- class SparseObjectTable
- {
- protected:
-
- long objectCount; // number of objects in the table
-
- SparseObjectPtr far * objects;
-
- SparseObjectPtr far * newObjectTable();
-
- public:
- SparseObjectTable(long aCount=0);
-
- SparseObjectPtr fetch(unsigned long n);
-
- void store(unsigned long, SparseObjectPtr);
- };
-
- SparseObjectPtr far * SparseObjectTable::newObjectTable()
- {
- SparseObjectPtr far *p;
- unsigned nObjects = 256;
- p = (SparseObjectPtr far *) pool.getMemory(nObjects*sizeof(SparseObjectPtr far *));
- if (!p) return 0;
- int i;
- for (i=0;i<nObjects;i++)
- p[i] = 0;
- return p;
- }
-
-
- SparseObjectTable::SparseObjectTable(long aCount) :
- objectCount(aCount),
- objects(0)
- {
- if (objectCount==0) {
- objectCount = 1l << 30;
- }
- }
-
- // returns a pointer to the n'th object
- SparseObjectPtr SparseObjectTable::fetch(unsigned long n)
- {
- if (n>=objectCount)
- return 0;
- unsigned char a = (n >> 24)&255;
- unsigned char b = (n >> 16)&255;
- unsigned char c = (n >> 8)&255;
- unsigned char d = n & 255;
-
- SparseObjectPtr far * p = objects;
- if (!p) return 0;
- p = (SparseObjectPtr far *) p[a];
- if (!p) return 0;
- p = (SparseObjectPtr far *) p[b];
- if (!p) return 0;
- p = (SparseObjectPtr far *) p[c];
- if (!p) return 0;
- p = (SparseObjectPtr far *) p[d];
- return p;
- }
-
- void SparseObjectTable::store(unsigned long n, SparseObjectPtr anObject)
- {
- if (n>=objectCount)
- return;
- if (!objects)
- objects = newObjectTable();
-
- SparseObjectPtr far * p = objects;
- unsigned char a = (n >> 24)&255;
- unsigned char b = (n >> 16)&255;
- unsigned char c = (n >> 8)&255;
- unsigned char d = n & 255;
-
- SparseObjectPtr far * q;
- q = (SparseObjectPtr far *) p[a];
- if (!q) p[a]=q=newObjectTable();
- p = q;
-
- q = (SparseObjectPtr far *) p[b];
- if (!q) p[b]=q=newObjectTable();
- p = q;
-
- q = (SparseObjectPtr far *) p[c];
- if (!q) p[c]=q=newObjectTable();
- p = q;
-
- p[d] = anObject;
- }
-
-
- //=====================================================================
- //
- // SpellingTable
- //
- // A class to manage the debug name information stored in an executable
- //
- //=====================================================================
- class SpellingTable : public SparseObjectTable
- {
- public:
- SpellingTable(long aCount=0) :
- SparseObjectTable(aCount) { }
-
-
- char far *operator[](unsigned long n)
- { return (char far *) fetch(n); }
-
- void store(unsigned long n, char far *anObject) {
- SparseObjectTable::store(n, anObject);
- }
- };
-
- //=====================================================================
- //
- // SymbolTable
- //
- // A class to manage the debug symbol information stored in an executable
- //
- //=====================================================================
- class SymbolTable : public SparseObjectTable
- {
- public:
- SymbolTable(long aCount=0) :
- SparseObjectTable(aCount) { }
-
-
- DebugSymbol far *operator[](unsigned long n)
- { return (DebugSymbol far *) fetch(n); }
-
- void store(unsigned long n, DebugSymbol far *anObject) {
- SparseObjectTable::store(n,anObject);
- }
- };
-
- //=====================================================================
- //
- // LineNumberTable
- //
- // A class to manage the debug line numbers stored in an executable
- //
- //=====================================================================
- class LineNumberTable : public SparseObjectTable
- {
- public:
- LineNumberTable(long aCount=0) :
- SparseObjectTable(aCount) { }
-
-
- DebugLineNumber far *operator[](unsigned long n)
- { return (DebugLineNumber far *) fetch(n); }
-
- void store(unsigned long n, DebugLineNumber far *anObject) {
- SparseObjectTable::store(n,anObject);
- }
- };
-
- //=====================================================================
- //
- // DebugInfo
- //
- // A class to manage the debug information stored in an executable
- //
- //=====================================================================
- class near DebugInfo
- {
- protected:
- RealModuleLoader *theModule;
- SpellingTable nameTable;
- SymbolTable symbols;
- LineNumberTable lineNumbers;
-
- unsigned codeviewHeader[8];
-
- DebugModule *modules;
- DebugSourceFile *sourceFiles;
- DebugScope *scopeRecords;
- DebugSegment *segments;
- DebugCorrelation *correlations;
-
- DebugHeader debugHeader;
-
- DebugExtHeader debugExtHeader;
-
- public:
- DebugInfo(RealModuleLoader *aModule) :
- theModule(aModule),
- nameTable(0),
- symbols(0),
- modules(0),
- sourceFiles(0),
- lineNumbers(0),
- scopeRecords(0),
- correlations(0),
- segments(0) { }
- int readDebugInfo();
- void readNames();
- void readSymbols();
- void readLineNumbers();
- char *symbolName(int i);
- char *moduleName(int i) { return symbolName( modules[i-1].moduleName ); }
- char *sourceName(int i) { return symbolName( sourceFiles[i-1].sourceFileName ); }
- char *describeFaultPc(WORD,WORD);
- alignmentShift() { return theModule->newHeader.fileAlignmentShift; }
- void loadError(char *msg) { theModule->loadErrorCount++; dprintf(msg); }
- void searchCorrelations(char *buf, DebugSegment *p, WORD ip);
-
- };
-
-
-
- char *DebugInfo::symbolName(int i) {
- static char buf[80];
- char *q = buf;
- char far *p = nameTable[i-1];
- if (!p) return "Unknown";
- int j;
- for (j=0; (j<79) && (*p);j++)
- *q++ = *p++;
- *q++ = 0;
- return buf;
- }
-
- void DebugInfo::searchCorrelations(char *lbuf, DebugSegment *p, WORD ip)
- {
- //dprintf("searchCorrelations(%04x)\n", ip);
- *lbuf = '\0';
- if (correlations) {
- DebugLineNumber far *aLine=0;
- DebugCorrelation *aCore = 0;
- int i;
- for (i=0;i<p->correlationCount;i++) {
- DebugCorrelation *correlation =
- correlations+p->correlationIndex+i-1;
- int ln;
- DebugSegment *seg = segments+correlation->segmentIndex-1;
- unsigned rip = ip; // - seg->codeOffset;
- //dprintf("relative offset=%04x of segment %d of correlation %d\n",
- // rip, correlation->segmentIndex, p->correlationIndex+i);
- for (ln=0;ln<correlation->linesCount;ln++) {
- DebugLineNumber far *line
- = lineNumbers[correlation->linesIndex+ln-1];
- //dprintf("line %d = %04x\n", line->lineNumberValue, line->lineNumberOffset);
- if (!aLine) {
- aCore = correlation;
- aLine = line;
- }
- else if (line->lineNumberOffset < rip &&
- line->lineNumberOffset > aLine->lineNumberOffset) {
- aCore = correlation;
- aLine = line;
- }
- }
- }
- if (aLine)
- sprintf(lbuf, "line %d of %s",
- aLine->lineNumberValue, sourceName(aCore->fileIndex) );
- }
- }
-
- //=====================================================================
- //
- // DebugInfo::descripeFaultPc
- //
- // given a logical CS:IP, describe in symbolic terms where
- // that is.
- //
- // This procedure does not take full advantage of the information
- // available in the debug symbol table.
- //
- // It just looks for the nearest symbol in that segment.
- //
- //=====================================================================
- char *DebugInfo::describeFaultPc(WORD lcs,WORD ip)
- {
- static char buf[80];
- static char mbuf[40];
- buf[0] = '\0';
- int i;
- if (segments) {
- for (i=0;i<debugHeader.segmentCount;i++) {
- DebugSegment *p = segments+i;
- if ( p->codeSegment == lcs &&
- ip >= p->codeOffset &&
- ip < p->codeOffset+p->codeLength ) {
-
- searchCorrelations(buf, p, ip);
- if (!buf[0]) {
- sprintf(buf,"%s+%04xh",
- moduleName(p->modIndex),
- ip-p->codeOffset );
- }
- // here we should search the correlations
- // starting at correlationIndex for correlationCount
- goto doSymbol;
- }
- }
- }
- // strcat(buf, "in Unknown module");
- doSymbol:
- DebugSymbol far *q = 0;
- for (i=0;i<debugHeader.symbolsCount;i++) {
- DebugSymbol far *p = symbols[i];
- if (lcs==p->symbolSegment&&p->symbolOffset<=ip)
- if (!q)
- q = p;
- else if (p->symbolOffset>q->symbolOffset)
- q = p;
- }
- if (q) {
- sprintf(mbuf, "%s+%04x",
- symbolName(q->symbolName),
- // q->symbolSegment,
- // q->symbolOffset,
- ip-q->symbolOffset);
- if (buf[0]) strcat(buf, " or ");
- strcat(buf, mbuf);
- goto done;
- }
- sprintf(buf, "Unknown func (%04x:%04x)",
- lcs, ip);
- done:
- // dprintf("describeFaultPc: %s\n", buf);
- return buf;
- }
-
- //=====================================================================
- //
- // readNames
- //
- // read name entries from the image
- //
- //=====================================================================
- void DebugInfo::readNames()
- {
- int inf = theModule->inf;
- const NameBufSize = 4096;
- char *buf = new char[NameBufSize];
- char name[80];
- unsigned long pos = 0;
- unsigned long namenr = 0;
- int n = 0;
- while (pos < debugHeader.names) {
- unsigned long nbytes = debugHeader.names-pos;
- if (nbytes>NameBufSize) nbytes = NameBufSize;
- int sz=read(inf, buf, nbytes);
- if (sz!=nbytes) {
- loadError("readNames read error\n");
- return;
- }
- int i;
- for (i=0;i<nbytes;i++) {
- name[n] = buf[i];
- if (n<79) n++;
- if (buf[i]==0) {
- char far *p = (char far *) pool.getMemory(n);
- _fstrcpy(p, name);
- n = 0;
- nameTable.store(namenr,p);
- namenr++;
- }
- }
- pos += nbytes;
- }
- delete [] buf;
- #ifdef DEBUGNAMES
- long i;
- for (i=0;i<namenr;i++) {
- char far *p = nameTable[i];
- _fstrcpy(name,p);
- dprintf("%04x:%04x Name Entry %ld: %s\n",
- FP_SEG(p), FP_OFF(p),
- i,
- name);
- }
- #endif
- }
-
- //=====================================================================
- //
- // readSymbols
- //
- // read symbol entries from the image
- //
- //=====================================================================
- void DebugInfo::readSymbols()
- {
- // read symbols
- dprintf("Symbol Table: %d symbols\n", debugHeader.symbolsCount);
-
- int inf = theModule->inf;
-
- DebugSymbol *aSymbol = new DebugSymbol[32];
- unsigned i=0;
- while(i<debugHeader.symbolsCount) {
- int k = debugHeader.symbolsCount-i;
- if (k>32) k = 32;
- int sz=read(inf, (void *) aSymbol, k*sizeof(DebugSymbol) );
- if (sz!=k*sizeof(DebugSymbol)) {
- loadError("readSymbols cannot read symbols\n");
- return;
- }
- DebugSymbol far *p = (DebugSymbol far *) pool.getMemory(k*sizeof(DebugSymbol));
- _fmemcpy(p, aSymbol, k*sizeof(DebugSymbol));
- int j;
- for (j=0;j<k;j++)
- symbols.store(i+j,p+j);
-
- i += k;
-
- }
-
- #ifdef DEBUGSYMBOLS
- for (i=0;i<debugHeader.symbolsCount;i++) {
- DebugSymbol far *p = symbols[i];
- dprintf("%04x:%04x Symbol %3d: %04x:%04x %s\n",
- FP_SEG(p), FP_OFF(p),
- i,
- p->symbolSegment,
- p->symbolOffset,
- symbolName(p->symbolName));
- }
- #endif
-
- delete [] aSymbol;
- }
-
- //=====================================================================
- //
- // readLineNumbers
- //
- // read line number entries from the image
- //
- //=====================================================================
- void DebugInfo::readLineNumbers()
- {
- // read line numbers
- unsigned i = 0;
- DebugLineNumber * aLine = new DebugLineNumber[128];
-
- int inf = theModule->inf;
-
- while (i<debugHeader.linesCount) {
- int k = debugHeader.linesCount-i;
- if (k>128) k = 128;
- int sz=read(inf, (void *) aLine, k*sizeof(DebugLineNumber) );
- if (sz!=k*sizeof(DebugLineNumber)) {
- loadError("readLineNumbers cannot read LineNumbers\n");
- return;
- }
- DebugLineNumber far *p = (DebugLineNumber far *) pool.getMemory(k*sizeof(DebugLineNumber));
- _fmemcpy(p, aLine, k*sizeof(DebugLineNumber));
- int j;
- for (j=0;j<k;j++)
- lineNumbers.store(i+j,p+j);
-
- i += k;
-
- }
-
- delete [] aLine;
- }
-
- //=====================================================================
- //
- // readDebugInfo
- //
- // read the Borland Debug information table from the image
- //
- //=====================================================================
- int DebugInfo::readDebugInfo()
- {
- dprintf("readDebugInfo\n");
- long mask = 1l << alignmentShift();
- long pos = theModule->endOfImage;
- int tries= 0;
- pos += mask-1;
- pos -= pos%mask;
-
- int inf = theModule->inf;
- {
- lseek(inf, pos, SEEK_SET);
- read(inf, (void *)&codeviewHeader, 16);
- dumpItem("CodeViewHeader", &codeviewHeader, sizeof(codeviewHeader));
- pos += sizeof(codeviewHeader);
- }
-
- retryLoad:
- lseek(inf, pos, SEEK_SET);
- unsigned sz=read(inf, (void *) &debugHeader, sizeof(DebugHeader) );
- if (sz!=sizeof(DebugHeader)) {
- dprintf("readDebugInfo cannot read header\n");
- return DPMI_OK;
- }
-
- dumpItem("DebugHeader", &debugHeader, sizeof(DebugHeader));
-
- if (debugHeader.magicNumber!=DEBUG_MAGIC) {
- if (tries) {
- dprintf("cannot find debug header\n");
- return DPMI_OK;
- }
- tries++;
- #ifndef DEBUGMAGIC
- unsigned *buf = new unsigned[256];
- DWORD npos = 0;
- dprintf("expected magic number at %08lxx\n", pos);
- lseek(inf, npos, SEEK_SET);
- for (;;) {
- if (read(inf, (char *)buf, 512)!=512) break;
- int i;
- for (i=0;i<256;i++)
- if (buf[i]==DEBUG_MAGIC) {
- pos = npos+2*i;
- dprintf("magic number found at %08lxx\n", npos+2*i);
- }
- npos += 512;
- }
- delete [] buf;
- goto retryLoad;
- #endif
-
- }
-
- unsigned bytes = sizeof(DebugExtHeader);
- if (bytes>debugHeader.extensionSize)
- bytes = debugHeader.extensionSize;
-
- dprintf("header extensionSize = %d\n", debugHeader.extensionSize);
-
- sz=read(inf, &debugExtHeader, bytes );
- if (sz!=bytes) {
- loadError("readDebugInfo cannot read header extention\n");
- return DPMI_ERR;
- }
-
- dumpItem("DebugExtHeader", &debugExtHeader, sizeof(DebugExtHeader));
-
- long symbolBase = pos + sizeof(DebugHeader)+debugHeader.extensionSize;
-
- lseek(inf, symbolBase+debugExtHeader.namePoolOffset, SEEK_SET);
-
- readNames();
-
- lseek(inf, symbolBase, SEEK_SET);
-
- readSymbols();
-
- // read modules
- if (debugHeader.modulesCount) {
- modules = new DebugModule[debugHeader.modulesCount];
- if (!modules) {
- loadError("cannot allocate modules\n");
- return DPMI_ERR;
- }
-
- bytes = debugHeader.modulesCount*sizeof(DebugModule);
- sz=read(inf, modules, bytes);
- if (sz!=bytes) {
- loadError("cannot read modules\n");
- return DPMI_ERR;
- }
-
- int i;
- for (i=0;i<debugHeader.modulesCount;i++) {
- DebugModule *p = modules+i;
- dprintf("Module %3d: %-20s\n",
- i, symbolName(p->moduleName));
- }
- }
-
- // read source files
- if (debugHeader.sourceCount) {
- sourceFiles = new DebugSourceFile[debugHeader.sourceCount];
- if (!sourceFiles) {
- loadError("cannot allocate sourceFiles\n");
- return DPMI_ERR;
- }
-
- bytes = debugHeader.sourceCount*sizeof(DebugSourceFile);
- sz=read(inf, sourceFiles, bytes);
- if (sz!=bytes) {
- loadError("cannot read sourceFiles\n");
- return DPMI_ERR;
- }
-
- int i;
- for (i=0;i<debugHeader.sourceCount;i++) {
- DebugSourceFile *p = sourceFiles+i;
- dprintf("SourceFile %3d: %-20s\n",
- i+1, symbolName(p->sourceFileName));
- }
- }
-
- readLineNumbers();
-
- // read scope records
- if (debugHeader.scopesCount) {
- scopeRecords = new DebugScope[debugHeader.scopesCount];
- if (!scopeRecords) {
- loadError("cannot allocate scope records\n");
- return DPMI_ERR;
- }
-
- bytes = debugHeader.scopesCount*sizeof(DebugScope);
- sz=read(inf, scopeRecords, bytes);
- if (sz!=bytes) {
- loadError("cannot read scope records\n");
- return DPMI_ERR;
- }
- }
-
- // read segments
- if (debugHeader.segmentCount) {
- segments = new DebugSegment[debugHeader.segmentCount];
- if (!segments) {
- loadError("cannot allocate segment records\n");
- return DPMI_ERR;
- }
-
- bytes = debugHeader.segmentCount*sizeof(DebugSegment);
- sz=read(inf, segments, bytes);
- if (sz!=bytes) {
- loadError("cannot read segment records\n");
- return DPMI_ERR;
- }
-
- int i;
- for (i=0;i<debugHeader.segmentCount;i++) {
- DebugSegment *p = segments+i;
- dprintf("Segment %3d: %04x:%04x,%04x %-20s\n",
- i+1, p->codeSegment, p->codeOffset, p->codeLength,
- moduleName(p->modIndex) );
- }
- }
-
- // read correlations
- if (debugHeader.correlationCount) {
- correlations = new DebugCorrelation[debugHeader.correlationCount];
- if (!correlations) {
- loadError("cannot allocate correlation records\n");
- return DPMI_ERR;
- }
-
- bytes = debugHeader.correlationCount*sizeof(DebugCorrelation);
- sz=read(inf, correlations, bytes);
- if (sz!=bytes) {
- loadError("cannot read correlation records\n");
- return DPMI_ERR;
- }
-
- int i;
- for (i=0;i<debugHeader.correlationCount;i++) {
- DebugCorrelation *p = correlations+i;
- dprintf("Correlation %3d: seg %3d file %3d lines %4d for %4d\n",
- i+1, p->segmentIndex, p->fileIndex, p->linesIndex, p->linesCount);
- }
- }
- return DPMI_OK;
- }
-
- //=====================================================================
- //
- // allocateSelectors
- //
- // allocates selectors and memory for the executable we are trying to
- // load.
- //
- // Note that all segments are set with access rights for a data
- // segment so that we can load and initialize them.
- //
- // Also, we create two selectors that point to the first segment,
- // because the FPU code wants to write to the code segment.
- //=====================================================================
- int allocateSelectors(int nSelectors, SegmentTable *segTable, Selector *selectors)
- {
- int i;
- unsigned baseSelector, selectorIncrement;
- int res;
-
- res = Dpmi.allocateLdtDescriptors(2*nSelectors+1, baseSelector);
- if (res!=0) {
- errprint("Cannot allocate ldt descriptors\n");
- return DPMI_ERR;
- }
-
- res = Dpmi.getSelectorIncrementValue(selectorIncrement);
- if (res!=0) {
- errprint("Cannot get selector increment value\n");
- return DPMI_ERR;
- }
-
- // get to an even selector so we can create a DS alias
- // for the first code segment.
-
- if (baseSelector&selectorIncrement) {
- Dpmi.freeSelector(baseSelector);
- baseSelector += selectorIncrement;
- }
- else {
- Dpmi.freeSelector(baseSelector+(nSelectors+1)*selectorIncrement);
- }
-
- for (i=1;i<=nSelectors;i++) {
- selectors[i] = baseSelector;
- baseSelector += selectorIncrement;
- // double allocate selectors for the first segment
- if (i==1)
- baseSelector += selectorIncrement;
- }
-
- // now allocate and map memory
-
- for (i=1;i<=nSelectors;i++) {
- unsigned memsize = segTable[i].allocatedSize;
- Selector selector = selectors[i];
- dprintf("Creating selector %d %04xh\n", i, selector);
- long handle, linear;
- int res = Dpmi.allocateMemory(memsize, linear, handle);
- dprintf("\tallocate_memory returns: %04xh, linear=%08xh, handle=%08lx\n",
- res, linear, handle);
- if (res!=DPMI_OK) return DPMI_ERR;
-
- res = Dpmi.lockMemory(linear, memsize);
- if (res!=DPMI_OK) return DPMI_ERR;
-
- do {
- dprintf("\tset selector base\n");
- res=Dpmi.setSelectorBase(selector, linear);
- if (res!=DPMI_OK) return DPMI_ERR;
- dprintf("\tset selector size\n");
- res=Dpmi.setSelectorLimit(selector, memsize);
- if (res!=DPMI_OK) return DPMI_ERR;
- dprintf("\tset access rights\n");
- res=Dpmi.setAccessRights(selector, AccessRightsData);
- if (res!=DPMI_OK) return DPMI_ERR;
- selector ^= selectorIncrement;
- } while ((i==1)&&(selector&selectorIncrement)!=0);
- }
- return DPMI_OK;
- }
-
- //=====================================================================
- //
- // adjustAccessRights
- //
- // Change the access rights for executable segments to be executable.
- //
- // This is probably the last thing we do before we're really ready to
- // run.
- //
- //=====================================================================
- int adjustAccessRights(int nSegs, SegmentTable *st, Selector *selectors)
- {
-
- int i;
- for (i=1;i<=nSegs;i++) {
- if ((st[i].attributes&7)==0) {
- dprintf("Segment %d is executable\n", i);
- int res=Dpmi.setAccessRights(selectors[i], AccessRightsCode);
- if (res!=DPMI_OK) return DPMI_ERR;
- }
- }
- return DPMI_OK;
- }
-
- //=====================================================================
- //
- // read_header
- //
- // read the header for the executable file
- //
- //=====================================================================
- void read_header(int inf, HEADER *header)
- {
- int i;
- char sig[3];
- i = read(inf,(char *) header, sizeof(HEADER) );
- if (i<sizeof(HEADER)) {
- dprintf("cannot read .exe header\n");
- exit(1);
- }
- sig[0] = header->signature[0];
- sig[1] = header->signature[1];
- sig[2]=0;
- dprintf(";signature = %s\n",sig);
- dprintf(";lastpagebytes = %d\n",header->lastpagebytes);
- dprintf(";numpages = %d\n",header->numpages);
- dprintf(";numreloc = %d\n",header->numreloc);
- dprintf(";headersize = %d\n",header->headersize);
- dprintf(";minalloc = %d\n",header->minalloc);
- dprintf(";maxalloc = %d\n",header->maxalloc);
- dprintf(";initialss = %04x\n",header->initialss);
- dprintf(";initialsp = %04x\n",header->initialsp);
- dprintf(";checksum = %04x\n",header->checksum);
- dprintf(";initialip = %04x\n",header->initialip);
- dprintf(";initialcs = %04x\n",header->initialcs);
- dprintf(";relocoffs = %04x\n",header->relocoffs);
- dprintf(";overlaynum = %04x\n",header->overlaynum);
- }
-
- //=====================================================================
- //
- // read_new_header
- //
- // read the new executable header.
- //
- //=====================================================================
- void read_new_header(int inf, NEHEADER *header)
- {
- int i;
- char sig[3];
- i = read(inf,(char *) header, sizeof(NEHEADER) );
- if (i<sizeof(NEHEADER)) {
- dprintf("cannot read new executable header\n");
- exit(1);
- }
- sig[0] = header->signature[0];
- sig[1] = header->signature[1];
- sig[2]=0;
- dprintf(";signature = %s\n",sig);
- if (sig[0]!='N'||sig[1]!='E') return;
- dprintf(";linker version %d.%d\n",
- header->linkMajor, header->linkMinor);
- dprintf(";entry table at 0x%04x for 0x%04x\n",
- header->entryOffset, header->entryLength);
- dprintf(";crc is 0x%08lx\n", header->crc);
- dprintf(";program flags are 0x%02x\n", header->programFlags);
- dprintf(";application flags are 0x%02x\n", header->applicationFlags);
- dprintf(";data segment index is 0x%04x\n", header->dataSegmentIndex);
- dprintf(";initialHeapSize is 0x%04x\n", header->initialHeapSize);
- dprintf(";initialStackSize is 0x%04x\n", header->initialStackSize);
- dprintf(";initialIP is %04x:%04x\n",
- header->initialCS,
- header->initialIP);
- dprintf(";Alignment Shift is %6d\n", header->fileAlignmentShift);
- dprintf(";Segment Count is %6d\n", header->segmentCount);
- dprintf(";SegmentTableOffset is 0x%04x\n", header->segmentTableOffset);
- }
-
- //=====================================================================
- //
- // read_segment_table
- //
- // read the segment table entries from a new executable
- //
- //=====================================================================
- void RealModuleLoader::read_segment_table(int inf, int nsegs, SegmentTable *tablePtr)
- {
- int i;
- char sig[3];
- int bytes = nsegs*sizeof(SegmentTable);
- i = read(inf,(char *) (tablePtr+1), bytes);
- if (i<bytes) {
- dprintf("cannot read segment table\n");
- exit(1);
- }
- for (i=1;i<=nsegs;i++) {
- SegmentTable *p = tablePtr + i;
- dprintf(";Segment[%d] at 0x%08lx, len=0x%04x, attr=0x%04x, alloc=0x%04x %s\n",i,
- ((long) p->offsetToSegment) << newHeader.fileAlignmentShift,
- p->length,
- p->attributes,
- p->allocatedSize,
- p->attributes&0x100?"relocations":"");
- }
- }
-
-
- //=====================================================================
- //
- // readRelocations reads the relocation entries for a segment and
- // applies them.
- //
- //=====================================================================
- int RealModuleLoader::readRelocations(int segNr, SegmentTable *st, Selector *selectors)
- {
- //-----------------------------------------------------------------------
- // The relocation table consists of a word containing the number of
- // relocation entries followed by the entries themselves.
- //
- // Each relocation entry has 4 words.
- //
- // Type of selector
- // | 0402 means only highword selector to xx
- // | 0002 means only highword selector to xx
- // | 0003 means full DWORD selector/offset
- // | 0005 means only offset within segment
- // | not sure about other relocation entries
- // |
- // | Offset to be repaired
- // | | Selector Value to insert
- // | | | Selector Offset
- // | | | |
- // v v v v
- // Entry 0: 0402 0001 0003 0000
- // Entry 1: 0402 005e 0003 02ca
- // Entry 2: 0402 00a3 0003 02ca
- // Entry 3: 0003 014d 0002 0000
- // Entry 4: 0402 181b 0001 1a06
- //
- //-----------------------------------------------------------------------
- // dprintf("reading relocation entries for %d\n", segNr);
- long pos = ((long) st->offsetToSegment) << newHeader.fileAlignmentShift;
- pos += st->length;
-
- lseek(inf, pos, SEEK_SET);
- WORD nEntries;
- unsigned bytes = read(inf, (char *)&nEntries, sizeof(WORD));
- if (bytes!=sizeof(WORD)) {
- errprint("error reading relocation entries\n");
- loadErrorCount++;
- return DPMI_ERR;
- }
-
- // adjust computed end of image so we can get to debug info OK.
-
- pos += sizeof(WORD) + nEntries*4*sizeof(WORD);
- if (pos>endOfImage) endOfImage = pos;
-
- // dprintf("there are %d entries\n", nEntries);
-
- WORD *relocTable = new WORD[nEntries*4];
- if (!relocTable) return DPMI_ERR;
-
- bytes=read(inf, (char *)(relocTable), 4*sizeof(WORD)*nEntries);
- if (bytes!=4*sizeof(WORD)*nEntries) {
- errprint("error reading relocation entries\n");
- loadErrorCount++;
- return DPMI_ERR;
- }
- int i;
- WORD *reloc = relocTable;
- for (i=0;i<nEntries;i++,reloc+=4) {
- // dprintf("\tRelocation Entry %2d: %04x %04x %04x %04x\n",
- // i, reloc[0], reloc[1], reloc[2], reloc[3]);
- unsigned targetType = reloc[0] >> 8;
- switch (targetType) {
- case 0:
- case 4:
- switch (reloc[0]&0xff) { // relocation type
- case 0x0002: // 16 bit selector
- {
- WORD _far *w;
- FP_SEG(w) = selectors[segNr];
- FP_OFF(w) = reloc[1];
- *w = selectors[reloc[2]];
- }
- break;
- case 0x0003:
- {
- WORD _far *w;
- FP_SEG(w) = selectors[segNr];
- FP_OFF(w) = reloc[1];
- *w++ = reloc[3];
- *w = selectors[reloc[2]];
- }
- break;
- case 0x0005:
- {
- WORD _far *w;
- FP_SEG(w) = selectors[segNr];
- FP_OFF(w) = reloc[1];
- *w = reloc[3];
- }
- break;
- default:
- dprintf("*\twhen reading relocation entries for %d:\n", segNr);
- dprintf("*\tBad Relocation Entry %2d: %04x %04x %04x %04x\n",
- i, reloc[0], reloc[1], reloc[2], reloc[3]);
- loadErrorCount++;
- break;
- }
- break;
- case 7:
- // these appear to be line number table fixups
- // I only get them when I compile with Line Number debug info
- break;
-
- default:
- dprintf("*\twhen reading relocation entries for %d:\n", segNr);
- dprintf("*\tBad Relocation Entry %2d: %04x %04x %04x %04x\n",
- i, reloc[0], reloc[1], reloc[2], reloc[3]);
- loadErrorCount++;
- }
- }
- delete [] relocTable;
- return DPMI_OK;
- }
-
- //=====================================================================
- //
- // readSegmentData reads the segment data (code) from the new
- // executable and then reads and applies the relocation entries.
- //
- //=====================================================================
- int RealModuleLoader::readSegmentData(int nsegs, SegmentTable *tablePtr, Selector *selectors)
- {
- int i;
- for (i=1;i<=nsegs;i++) {
- SegmentTable *st = tablePtr+i;
- char _far *p = 0;
- FP_SEG(p) = selectors[i];
- long pos = ((long) st->offsetToSegment) << newHeader.fileAlignmentShift;
- lseek(inf, pos, SEEK_SET);
- DWORD bytes = lread(inf, p, DWORD(st->length) );
- if (bytes!=st->length) return DPMI_ERR;
- if (pos+bytes>endOfImage)
- endOfImage = pos+bytes;
- dprintf("Load Segment %d, pos=%08lx, bytes=%08lx, end=%08lx\n",
- i, pos, bytes, endOfImage);
- }
-
- for (i=1;i<=nsegs;i++) {
- SegmentTable *p = tablePtr + i;
- if (p->attributes&0x100) {
- readRelocations(i, tablePtr+i, selectors);
- }
- }
- return DPMI_OK;
- }
-
-
- //=====================================================================
- //
- // RealModuleLoader Class Methods
- //
- //=====================================================================
-
- SegmentTable *RealModuleLoader::allocSegTables(int n)
- {
- segTable = new SegmentTable[n];
- return segTable;
- }
-
- Selector *RealModuleLoader::allocSelectors(int n)
- {
- selectors = new Selector[n];
- return selectors;
- }
-
- void RealModuleLoader::adjustSelectors()
- {
- dprintf("adjust selectors: segs = %d, segtable = %08lx, selectors=%08lx\n",
- newHeader.segmentCount, segTable, selectors);
- adjustAccessRights(newHeader.segmentCount, segTable, selectors);
- }
-
- void _far *RealModuleLoader::entryPoint()
- {
- void _far *p;
- FP_SEG(p) = selectors[newHeader.initialCS];
- FP_OFF(p) = newHeader.initialIP;
- dprintf("program entry point is: %04x:%04x\n", FP_SEG(p), FP_OFF(p) );
- return p;
- }
-
- int RealModuleLoader::getLogicalSelector(WORD cs, WORD& lcs)
- {
- WORD i;
- for (i=1;i<newHeader.segmentCount;i++)
- if (selectors[i]==cs) {
- lcs = i;
- return 1;
- }
- return 0;
- }
-
- char *RealModuleLoader::describeFaultPc(WORD& nearCs, WORD cs, WORD ip)
- {
- static char buf[20];
- WORD lcs;
- if (cs==_CS) {
- sprintf(buf, "dpmirun %04x:%04x", cs, ip);
- return buf;
- }
- else if (getLogicalSelector(cs, lcs))
- nearCs = cs;
- else { // probably a near call
- if (!getLogicalSelector(nearCs, lcs)) {
- sprintf(buf, "physical %04x:%04x", cs, ip);
- return buf;
- }
- }
- return debugInfo->describeFaultPc(lcs,ip);
- }
-
- void far *RealModuleLoader::getStack(unsigned stkSize)
- {
- Selector stkSelector;
- if (Dpmi.getMappedMemory(stkSize, stkSelector, AccessRightsData)!=DPMI_OK)
- return NULL;
- return MK_FP(stkSelector, 0);
- }
-
- //=====================================================================
- //
- // loadExecutable
- //
- // This routine loads the executable and returns a ModuleLoader
- // object to deal with the results.
- //
- //=====================================================================
- void RealModuleLoader::loadExecutable(char *exeName)
- {
- strcpy(fname,exeName);
- inf = open(fname, O_RDONLY|O_BINARY);
- if (inf<0) {
- errprint("input %s not found\n",fname);
- Dpmi.dosExit(1);
- }
-
- read_header(inf,&header);
- headeroffset = ((long) header.headersize)*16;
- lastbyte = ((long) header.numpages)*512 + header.lastpagebytes;
-
- headeroffset = ((long) header.morejunk[14]);
-
- lseek(inf, headeroffset, SEEK_SET);
-
- read_new_header(inf, &newHeader);
-
- lseek(inf, headeroffset+newHeader.segmentTableOffset, SEEK_SET);
-
- segTable = allocSegTables( newHeader.segmentCount+1 );
- if (!segTable) {
- errprint("cannot allocate segTable\n");
- Dpmi.dosExit(1);
- }
-
- selectors = allocSelectors(newHeader.segmentCount+1);
- if (!selectors) {
- errprint("cannot allocate selectors array\n");
- Dpmi.dosExit(1);
- }
-
- read_segment_table(inf, newHeader.segmentCount, segTable);
-
- if (allocateSelectors(newHeader.segmentCount, segTable, selectors)!=DPMI_OK) {
- errprint("cannot allocate selectors\n");
- Dpmi.dosExit(1);
- }
- if (readSegmentData(newHeader.segmentCount, segTable, selectors)!=0) {
- errprint("cannot read executable data\n");
- }
-
- debugInfo = new DebugInfo(this);
- debugInfo->readDebugInfo();
-
- close(inf);
-
- dprintf("executable all loaded...\n");
- }
-
- //=====================================================================
- //
- // newModuleLoader
- //
- // return a new RealModuleLoader as a real instance of the
- // abstract class ModuleLoader.
- //
- //=====================================================================
- ModuleLoader *newModuleLoader()
- {
- return new RealModuleLoader;
- }
-
-
-
-
-
-
-